#ifndef __MEMORY_PADDR_H__
#define __MEMORY_PADDR_H__

#include <common.h>

#define PMEM_LEFT  ((paddr_t)CONFIG_MBASE)
#define PMEM_RIGHT ((paddr_t)CONFIG_MBASE + CONFIG_MSIZE - 1)
#define PMEM_RESET (PMEM_LEFT + CONFIG_PC_RESET_OFFSET)

#define DMEM_LEFT  ((ioaddr_t)CONFIG_DBASE)
#define DMEM_RIGHT ((ioaddr_t)CONFIG_DBASE + CONFIG_DSIZE - 1)
#define DMEM_RESET (PMEM_LEFT + CONFIG_DEV_RESET_OFFSET)


uint8_t* paddr_to_ptr(paddr_t paddr);
paddr_t ptr_to_paddr(uint8_t *haddr);
// uint8_t* paddr_to_flash_ptr(paddr_t paddr);
// uint8_t* paddr_to_psram_ptr(paddr_t paddr);
uint8_t* paddr_to_sdram_ptr(paddr_t paddr);
uint8_t* ioaddr_to_ptr(ioaddr_t ioaddr);
ioaddr_t ptr_to_ioaddr(uint8_t *haddr);


static inline bool in_pmem(paddr_t addr) {
    return addr - CONFIG_MBASE <= CONFIG_MSIZE;
}

// static inline bool in_flash(ioaddr_t addr) {
//     return addr - CONFIG_DBASE_FLASH <= CONFIG_DBASE_FLASH;
// }

// static inline bool in_psram(ioaddr_t addr) {
//     return addr - CONFIG_DBASE_PSRAM <= CONFIG_DSIZE_PSRAM;
// }

static inline bool in_sdram(ioaddr_t addr) {
    return addr - CONFIG_DBASE_SDRAM <= CONFIG_DSIZE_SDRAM;
}

static inline bool in_dmem(ioaddr_t addr) {
    bool in_uart  = addr - CONFIG_DBASE_UART <= CONFIG_DSIZE_UART && addr - CONFIG_DBASE_UART >= 0;
    bool in_amdev = addr - CONFIG_DBASE      <= CONFIG_DSIZE && addr - CONFIG_DBASE >= 0;
    return in_uart || in_amdev;
}


word_t paddr_read(paddr_t addr, int len, word_t pc);
void paddr_write(paddr_t addr, int len, word_t data, word_t pc);
word_t device_read(ioaddr_t addr, int len);
void device_write(ioaddr_t addr, int len, word_t data);

void mem_init();
#endif
